import json
import re
from typing import Dict, List, Optional, Tuple
import openpyxl
from openpyxl.cell import Cell
from openpyxl.worksheet.worksheet import Worksheet
from playwright.sync_api import sync_playwright


class ExcelTemplateReader:
    def __init__(self, file_path: str):
        self.file_path = file_path
        self.workbook = openpyxl.load_workbook(file_path, data_only=True)
        self.validation_rules = {}
    
    def _extract_validation_rules(self, header_cell: Cell, description_cell: Cell) -> Dict:
        """从描述单元格中提取验证规则"""
        rules = {}
        desc = str(description_cell.value or "")
        
        # 必填检查
        rules["required"] = "*" in str(header_cell.value or "")
        
        # 长度限制
        length_match = re.search(r"长度不能超过 (\d+) 个字符", desc)
        if length_match:
            rules["max_length"] = int(length_match.group(1))
        
        # 下拉选项
        if "下拉框选择" in desc:
            options_match = re.search(r"选择说明：\s*([\s\S]+?)(?:\n|$)", desc)
            if options_match:
                options = [opt.strip() for opt in options_match.group(1).split("\n") if opt.strip()]
                rules["options"] = options
        
        # 数据类型
        if "IP段" in str(header_cell.value or ""):
            rules["type"] = "ip_or_domain"
        elif "联系方式" in str(header_cell.value or ""):
            rules["type"] = "phone"
        elif "邮箱" in str(header_cell.value or ""):
            rules["type"] = "email"
        
        return rules
    
    def _validate_field(self, field_name: str, value: str, rules: Dict) -> Tuple[bool, str]:
        """验证单个字段是否符合规则"""
        if not value and rules.get("required", False):
            return False, f"{field_name} 是必填字段"
        
        if value:
            # 长度检查
            if "max_length" in rules and len(value) > rules["max_length"]:
                return False, f"{field_name} 长度不能超过 {rules['max_length']} 个字符"
            
            # 下拉选项检查
            if "options" in rules and value not in rules["options"]:
                return False, f"{field_name} 必须是以下选项之一: {', '.join(rules['options'])}"
            
            # 数据类型检查
            if rules.get("type") == "email" and not re.match(r"^[^@]+@[^@]+\.[^@]+$", value):
                return False, f"{field_name} 必须是有效的邮箱格式"
            
            if rules.get("type") == "phone" and not re.match(r"^1[3-9]\d{9}$", value):
                return False, f"{field_name} 必须是有效的手机号格式"
            
            if rules.get("type") == "ip_or_domain" and not (
                re.match(r"^(\d{1,3}\.){3}\d{1,3}(:\d+)?$", value) or 
                re.match(r"^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$", value)
            ):
                return False, f"{field_name} 必须是有效的IP地址或域名"
        
        return True, ""

    def read_application_data(self, sheet_name: str = "注册") -> List[Dict]:
        """读取并验证应用数据"""
        try:
            sheet = self.workbook[sheet_name]
        except KeyError:
            raise ValueError(f"工作表 '{sheet_name}' 不存在")
        
        # 第一行是表头，第二行是描述/规则，数据从第三行开始
        headers = [cell.value for cell in sheet[1]]
        descriptions = [cell.value for cell in sheet[2]]
        
        # 提取每个字段的验证规则
        # field_rules = {}
        # for i, (header, desc_cell) in enumerate(zip(headers, sheet[2]), 1):
        #     if header:
        #         field_rules[header] = self._extract_validation_rules(sheet.cell(row=1, column=i), desc_cell)
        
        applications = []
        error_messages = []
        
        # 从第15行开始读取数据
        for row in sheet.iter_rows(min_row=15, values_only=False):
            # 跳过空行
            if not any(cell.value for cell in row):
                continue
            
            app_data = {}
            valid = True
            
            for header, cell in zip(headers, row):
                if not header:  # 跳过无表头的列
                    continue
                
                value = str(cell.value).strip() if cell.value else ""
                # rules = field_rules.get(header, {})
                
                # 验证字段
                # is_valid, message = self._validate_field(header, value, rules)
                # if not is_valid:
                #     error_messages.append(f"行 {cell.row}: {message}")
                #     valid = False
                
                # 只有有值的字段才添加到数据中
                if value:
                    app_data[header] = value
            
            if app_data:  # 只有有效且非空的数据才添加
                applications.append(app_data)
        
        if error_messages:
            print("数据验证发现以下问题:")
            for msg in error_messages:
                print(f" - {msg}")
        
        return applications


def extract_text_before_brackets(text):
    """
    抽取括号前面的文字信息并返回为字符串
    如果有多个匹配结果，会用逗号分隔连接
    """
    # 匹配中文字符、英文字母和下划线（可根据需要调整匹配范围）
    pattern = r'([\w\u4e00-\u9fa5]+)\s*[\(\（]'
    # 查找所有匹配项
    matches = re.findall(pattern, text)
    if not matches:
        return ""  # 没有匹配项返回空字符串
    # 用逗号+空格连接所有匹配项
    return "".join(matches)

def fill_form_with_playwright(form_data: Dict,username:str,pwd:str):
    """使用Playwright自动填充表单"""
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        page = browser.new_page()
        try:
            # 假设表单页面URL - 实际使用时替换为真实URL
            page.goto("http://adm.esbgateway.sgcc.com.cn")

            # 等待表单加载完成
            page.wait_for_selector("form")
            page.get_by_role("button", name="立即登录").click()
            page.locator("#department").click()
            page.get_by_role("link", name="公司总部").click()
            page.locator("#username").click()
            page.locator("#username").fill(username)
            page.locator("#username").press("Tab")
            page.locator("#password").fill(pwd)
            page.locator("#password").press("Tab")
            page.get_by_role("button", name="登录").click()

            # 等待表单加载完成
            page.wait_for_selector("form")
            page.get_by_role("menuitem", name=" 应用信息管理").locator("span").click()
            page.get_by_role("button", name=" 新 增").click()
            page.get_by_role("textbox", name="请选择 建设类型").click()
            page.get_by_role("listitem").filter(has_text=form_data.get("*建设类型")).locator("span").click()
            page.get_by_role("textbox", name="请输入应用名称").click()
            page.get_by_role("textbox", name="请输入应用名称").fill(form_data.get("*应用/微应用名称"))
            page.get_by_role("textbox", name="请输入 应用描述").click()
            page.get_by_role("textbox", name="请输入 应用描述").fill(form_data.get("*应用/微应用描述"))
            page.locator("div").filter(has_text=re.compile(r"^省份:总部国网河北电力应用级别:全网级总部级省级地市级县区级班组级$")).locator("i").first.click()
            page.locator("div").filter(has_text=re.compile(r"^省份:总部国网河北电力应用级别:全网级总部级省级地市级县区级班组级$")).locator("i").nth(1).click()
            app_level = form_data.get("*应用级别")
            app_level = extract_text_before_brackets(app_level)
            page.get_by_text(app_level).click()
            page.locator("div:nth-child(5) > div > .el-form-item > .el-form-item__content > .el-select > .el-input > .el-input__suffix > .el-input__suffix-inner > .el-select__caret").click()
            page.locator("div:nth-child(16) > .el-scrollbar > div:nth-child(3) > .el-scrollbar__thumb").click()
            page.get_by_text(form_data.get("*主管业务部门（专业）")).click()
            page.get_by_role("textbox", name="请输入 部门联系人").click()
            page.get_by_role("textbox", name="请输入 部门联系人").fill(form_data.get("*业务部门联系人"))
            page.get_by_role("textbox", name="请输入 部门联系方式").click()
            page.get_by_role("textbox", name="请输入 部门联系方式").fill(form_data.get("*业务部门联系方式"))
            page.get_by_role("textbox", name="请输入 承建厂商").click()
            page.get_by_role("textbox", name="请输入 承建厂商").fill(form_data.get("*承建厂商"))
            page.get_by_role("textbox", name="请输入 厂商联系人").click()
            page.get_by_role("textbox", name="请输入 厂商联系人").fill(form_data.get("*厂商联系人"))
            page.get_by_role("textbox", name="请输入 厂商联系方式").click()
            page.get_by_role("textbox", name="请输入 厂商联系方式").fill(form_data.get("*厂商联系方式"))
            page.get_by_role("textbox", name="请输入 内网邮箱").click()
            page.get_by_role("textbox", name="请输入 内网邮箱").fill(form_data.get("*厂商内网邮箱"))
            page.get_by_role("textbox", name="请选择 主依赖中台").click()
            page.get_by_text(form_data.get("主依赖中台")).click()
            page.get_by_role("button", name="生成随机密钥").click()
            # page.get_by_role("button", name="提 交").click()
            
        # except Exception as e:
        #     print(f"自动化过程中发生错误: {str(e)}")
        #     # 保存错误截图
        #     page.screenshot(path="form_fill_error.png")
        finally:
            # browser.close()
            page.screenshot(path="form_fill_sucess.png")


def main(filepath:str,username:str,pwd:str):

    try:
        # 1. 读取并验证Excel数据
        reader = ExcelTemplateReader(filepath)
        applications = reader.read_application_data()
        
        if not applications:
            print("未找到有效的应用数据")
            return
        
        # 打印提取的数据（调试用）
        print("提取的有效应用数据:")
        for i, app_data in enumerate(applications, 1):
            print(f"\n应用 #{i}:")
            print(json.dumps(app_data, ensure_ascii=False, indent=2))
        
        # 2. 使用Playwright自动填充表单（以第一个应用为例）
        if applications:
            print("\n开始自动填充表单...")
            fill_form_with_playwright(applications[0],username,pwd)
        
    except Exception as e:
        print(f"程序运行出错: {str(e)}")


if __name__ == "__main__":
    # 使用HTTP传输替代stdio
    # mcp.run(transport="streamable-http", host="0.0.0.0", port=8000)
    main("d:\\统一服务调度组件运营表单（国网西北分部-气象数据综合服务应用）.xlsx","admin","123456")
    # 示例用法
    # text = "总部级（服务于西北分部）"
    # matches = extract_text_before_brackets(text)
    # print(matches)  # 输出: 总部级